// gorpc/client/client.go

package client

import (
	"errors"
	"gorpc/client/service"
	"gorpc/codec"
	"gorpc/common"
	"gorpc/protocol"
	"gorpc/transport"
)

type CalcServiceProxy struct {
	transport *transport.TCPTransport
}

func NewCalcServiceProxy(t *transport.TCPTransport) service.CalcService {
	return &CalcServiceProxy{transport: t}
}

func (p *CalcServiceProxy) process(req *protocol.Message, args *common.CalcArgs) (int, error) {
	if err := req.SerializeBody(args, codec.JSON); err != nil {
		return 0, err
	}

	conn, err := p.transport.Dial()
	if err != nil {
		return 0, err
	}
	defer conn.Close()

	if err := p.transport.Write(conn, req); err != nil {
		return 0, err
	}

	resp, err := p.transport.Read(conn)
	if err != nil {
		return 0, err
	}

	if resp.Header.Error != "" {
		return 0, errors.New(resp.Header.Error)
	}

	var reply common.CalcReply
	if err := resp.DeserializeBody(&reply); err != nil {
		return 0, err
	}

	return reply.Result, nil
}

func (p *CalcServiceProxy) Add(a, b int) (int, error) {
	args := &common.CalcArgs{A: a, B: b}
	req := protocol.NewMessage("Add")
	return p.process(req, args)
}

// 其他方法类似...

func (p *CalcServiceProxy) Sub(a, b int) (int, error) {
	args := &common.CalcArgs{A: a, B: b}
	req := protocol.NewMessage("Sub")
	return p.process(req, args)
}

func (p *CalcServiceProxy) Mul(a, b int) (int, error) {
	args := &common.CalcArgs{A: a, B: b}
	req := protocol.NewMessage("Mul")
	return p.process(req, args)
}

func (p *CalcServiceProxy) Div(a, b int) (int, error) {
	args := &common.CalcArgs{A: a, B: b}
	req := protocol.NewMessage("Div")
	return p.process(req, args)
}

func (p *CalcServiceProxy) Mod(a, b int) (int, error) {
	args := &common.CalcArgs{A: a, B: b}
	req := protocol.NewMessage("Mod")
	return p.process(req, args)
}
